package com.ww.juc.forkjoin;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ExecuteTaskDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        test02();
    }

    static void test02() throws ExecutionException, InterruptedException {
        Job job = new Job(urls, 0, urls.size());
        ForkJoinTask<String> forkJoinTask = forkJoinPool.submit(job);
        String result = forkJoinTask.get();
        System.out.println(result);
    }

    static void test01() throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(4);
        List<Future> futures = new ArrayList<>();
        int size = urls.size();
        int groupSize = 10;
        int groupCount = (size - 1) / groupSize + 1;

        for (int groupIndex = 0; groupIndex < groupCount - 1; groupIndex++) {
            int leftIndex = groupSize * groupIndex;
            int rightIndex = groupSize * (groupIndex + 1);

            Future<String> future = pool.submit(new Task(leftIndex, rightIndex));
            futures.add(future);
        }

        int i = 1;
        for (Future future : futures) {
            System.out.println(i++ + "===================");
            System.out.println(future.get());
        }

        pool.shutdown();
    }

    static List<String> urls = new ArrayList<>();

    static {
        for (int i = 0; i < 10000; i++) {
            if (0 == i % 2) {
                urls.add("http://www.baidu.com");
            } else {
                urls.add("http://www.sina.cn");
            }
        }
    }

    static String doRequest(String url) {
        return "send ..." + url + "\n";
    }

    static ForkJoinPool forkJoinPool = new ForkJoinPool(3, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);

    static class Job extends RecursiveTask<String> {
        List<String> urls;
        int start;
        int end;

        public Job(List<String> urls, int start, int end) {
            this.urls = urls;
            this.start = start;
            this.end = end;
        }

        @Override
        protected String compute() {
            int count = end - start;

            if (count <= 10) {
                String rs = "";
                for (int i = start; i < end; i++) {
                    String response = doRequest(urls.get(i));
                    rs += response;
                }
                return rs;
            } else {
                int x = (start + end) / 2;
                Job job1 = new Job(urls, start, x);
                job1.fork();
                Job job2 = new Job(urls, x, end);
                job2.fork();

                String rs = "";
                rs += job1.join();
                rs += job2.join();
                return rs;
            }
        }
    }

    static class Task implements Callable<String> {
        int start;
        int end;

        public Task(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        public String call() throws Exception {
            StringBuilder sb = new StringBuilder();
            for (int i = start; i < end; i++) {
                sb.append(doRequest(urls.get(i)));
            }
            return sb.toString();
        }
    }
}
